//////////////////////////////////////////////
// Texture.h
//
//////////////////////////////////////////////

/// Defines / Macros -------------------------

#pragma once

/// Forward decl -----------------------------

namespace nkGraphics
{
	class System ;

	struct ImageDataDescriptor ;
	struct MapRequestDescriptor ;
	struct ResourceGpuCopyDescriptor ;
	struct TextureCpuDataDescriptor ;
	struct UnmapRequestDescriptor ;
}

namespace nkImages
{
	class Image ;
	class ImageView ;
}

/// Includes ---------------------------------

// nkGraphics
#include "../Dll/DllDefines.h"

#include "../Buffers/Enums/BufferBindFlag.h"
#include "../Buffers/Enums/BufferCpuAccessFlag.h"
#include "../Buffers/Enums/BufferUsage.h"

#include "../Buffers/MapResult.h"

#include "../Resources/Enums/ResourceMiscFlag.h"

#include "../Resources/ShaderResource.h"

#include "../Utils/DxDefinesWrapper.h"

// nkExport
#include <NilkinsExport/Exportable/Exportable.h>

// nkMemory
#include <NilkinsMemory/Containers/Buffer.h>
#include <NilkinsMemory/Containers/BufferView.h>

#include <NilkinsMemory/Pointers/UniquePtr.h>

/// Internals --------------------------------

namespace nkGraphics
{
	enum class TEX_TYPE
	{
		TEX_2D = 0,
		TEX_3D,
		TEX_CUBEMAP
	} ;

	enum class TEX_RENDER_FLAG
	{
		NO_RENDER = 0,
		RENDER_TARGET,
		DEPTH_RENDER_TARGET
	} ;
}

/// Class ------------------------------------
	
namespace nkGraphics
{
	class DLL_GRAPHICS_EXPORT Texture : public ShaderResource, public nkExport::Exportable
	{		
		public :
		
			// Destructor
			virtual ~Texture () ;

			// Getters
			TextureCpuDataDescriptor* getCpuData () const ;
			unsigned int getCpuSliceCount () const ;
			bool isFromFile () const ;
			bool isGammaCorrected () const ;
			bool isBackBufferTex () const ;
			TEX_TYPE getTexType () const ;
			TEX_RENDER_FLAG getRenderFlag () const ;
			unsigned int getNeededMipsForSize () const ;

			// Parameters getters
			virtual int getWidth () const = 0 ;
			virtual int getHeight () const = 0 ;
			virtual int getDepthOrArraySize () const = 0 ;
			virtual unsigned int getMipLevels () const = 0 ;
			virtual FORMAT getTextureFormat () const = 0 ;
			virtual BUFFER_CPU_ACCESS_FLAG getCpuAccessRights () const = 0 ;
			virtual BUFFER_USAGE getTextureUsage () const = 0 ;
			virtual BUFFER_BIND_FLAG getTextureBinding () const = 0 ;
			virtual RESOURCE_MISC_FLAG getMiscFlag () const = 0 ;
			virtual unsigned int getSampleCount () const = 0 ;
			virtual unsigned int getSampleQuality () const = 0 ;
			virtual bool getAutoMipGeneration () const = 0 ;

			// Setters
			void addCpuDataSlice (const nkMemory::BufferView<>& data, unsigned int byteOffset = 0u, unsigned int rowByteSize = 0u, unsigned int sliceByteSize = 0u) ;
			void addCpuDataSliceCopy (const nkMemory::BufferView<>& data, unsigned int byteOffset = 0u, unsigned int rowByteSize = 0u, unsigned int sliceByteSize = 0u) ;
			void addCpuDataSliceForward (nkMemory::Buffer&& data, unsigned int byteOffset = 0u, unsigned int rowByteSize = 0u, unsigned int sliceByteSize = 0u) ;
			void addCpuDataSliceRelativeToLast (unsigned int byteOffset = 0u, unsigned int rowByteSize = 0u, unsigned int sliceByteSize = 0u) ;
			void setFromImage (const nkImages::ImageView& image) ;
			void setFromImageCopy (const nkImages::ImageView& image) ;
			void setFromImageForward (nkImages::Image&& image) ;
			void setBackBufferTex (bool value) ;
			virtual void freeCpuData () ;
			virtual void setGammaCorrected (bool value) ;
			virtual void setPath (nkMemory::StringView value) override ;

			// Parameters setters
			virtual void setWidth (unsigned int width) = 0 ;
			virtual void setHeight (unsigned int height) = 0 ;
			virtual void setDepthOrArraySize (unsigned int depth) = 0 ;
			virtual void setMipLevels (unsigned int value) = 0 ;
			virtual void setTextureFormat (FORMAT format) = 0 ;
			virtual void setCpuAccessRights (BUFFER_CPU_ACCESS_FLAG rights) = 0 ;
			virtual void setTextureUsage (BUFFER_USAGE usage) = 0 ;
			virtual void setTextureBinding (BUFFER_BIND_FLAG binding) = 0 ;
			virtual void setAutoMipGeneration (bool value) = 0 ;
			virtual void copyParams (const Texture& other) = 0 ;

			void setTextureFormatFromString (nkMemory::StringView str) ;

			// Preparations
			void setMightManuallyGenerateMip (bool value) ;
			virtual void prepareAsTexture2d () ;
			virtual void prepareAsCubemap () ;
			virtual void prepareAsTexture3d () ;
			virtual void setRenderFlag (TEX_RENDER_FLAG value) ;
			virtual void generateMipChain (unsigned int fromMip = 0) = 0 ;

			// Mapping
			nkImages::Image convertToImage (int mip, int sliceOrArrayIndex) ;
			virtual MapResult map (const MapRequestDescriptor& requestDesc) = 0 ;
			virtual void unmap (const UnmapRequestDescriptor& requestDesc) = 0 ;
			virtual void gpuCopyFrom (Texture& other, const ResourceGpuCopyDescriptor& descriptor) = 0 ;

			// Import / export
			virtual void exportClassToTree (nkExport::Node* rootNode) override ;
			virtual void importClassFromTree (nkExport::Node* rootNode) override ;

		public :

			// Statics
			static nkMemory::UniquePtr<Texture> create (System* system = nullptr) ;

		protected :

			// Functions
			// Constructor
			Texture (System* system) noexcept ;

			// Load
			bool _prepareCpuDataForLoad () ;

			// Cpu data getters
			unsigned int _getFilledCpuSliceCount () const ;
			nkMemory::BufferView<> _getCpuSliceData (unsigned int index) const ;
			unsigned int _getCpuSliceByteOffset (unsigned int index) const ;
			unsigned int _getCpuSliceRowSize (unsigned int index) const ;
			unsigned int _getCpuSliceByteSize (unsigned int index) const ;
			bool _getCpuSliceDataIsView (unsigned int index) const ;
			nkMemory::Buffer _getCpuSliceDataTransfer (unsigned int index) ;

		protected :
		
			// Attributes
			// CPU data if required, as data pointer or image info
			TextureCpuDataDescriptor* _cpuData ;
			ImageDataDescriptor* _imageData ;

			// Internal type and flags
			TEX_TYPE _texType ;
			TEX_RENDER_FLAG _renderFlag ;

			// Witnesses
			bool _fromFile ;
			// If we want gamma correction on the data, useful for diffuse, albedo...
			// Textures containing raw data (normal map for instance) should not be corrected
			bool _gammaCorrect ;
			// Whether this texture is a proxy for a context back buffer
			bool _backBufferTex ;
			// Whether manual mip generation might happen
			bool _mightManuallyGenerateMip ;
	} ;
}